﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using COFE.Core;
using COFE.Core.Profile;

namespace COFE.Core.Utils
{
    /// <summary>
    /// COFE version of System.IO.Directory static class, provide methods to manipulate directories.
    /// </summary>
    public class DirectoryServices : IDirectoryServices
    {
        #region Constructors

        internal DirectoryServices(IUserProfile profile)
        {
            UserProfile = profile;         
        }

        #endregion

        #region Methods

        public IDirectoryInfo CreateDirectory(string path)
        {
            string[] pathSplit = path.Split(new char[] { '\\' });

            string curPath = "";
            string lastPath = "";
            int idx = 0;
            
            while (idx < pathSplit.Length && (UserProfile.Directory.Exists(curPath) || UserProfile.File.Exists(curPath)))
            {
                lastPath = curPath;
                string curFragment = pathSplit[idx++];
                curPath = curPath != null ? COFEPath.Combine(curPath, curFragment) : curFragment;
                if (curPath.EndsWith(":")) curPath += "\\";
            }

            if (UserProfile.Directory.Exists(curPath) || UserProfile.File.Exists(curPath))
                lastPath = curPath;
            else idx--;

            IDirectoryInfo dir = UserProfile.TryParseNonCachePath(lastPath) as IDirectoryInfo;

            if (dir == null)
                throw new ArgumentException(lastPath + " doesn't exits.");
            
            for (int i = idx; i < pathSplit.Length; i++)
            {
                dir = dir.CreateDirectory(pathSplit[i]);
            }

            return dir;
        }

        public IDirectoryInfo CreateVirtualDirectory(string path, string type)
        {
            string parentPath = COFEPath.GetDirectoryName(path);
            string dirName = COFEPath.GetFileName(path);
            CreateDirectory(parentPath);
            IDirectoryInfo parentDir = UserProfile.TryParseNonCachePath(parentPath) as IDirectoryInfo;
            if (parentDir == null)
                throw new Exception("Cannot find " + parentDir);
            if (type == null)
                return parentDir.CreateDirectory(dirName);
            else return parentDir.CreateVirtualDirectory(dirName, type);
        }
       
        public void Copy(string sourceDirectoryPath, string destDirectoryPath)
        {
            IDirectoryInfo sourceInfo = (IDirectoryInfo)UserProfile.TryParseNonCachePath(sourceDirectoryPath);
            IDirectoryInfo destInfo = (IDirectoryInfo)UserProfile.TryParseNonCachePath(destDirectoryPath);
            if (sourceInfo == null) throw new System.IO.FileNotFoundException("Source not found", sourceDirectoryPath);
            if (destInfo == null) throw new System.IO.FileNotFoundException("Destation directory not found", destDirectoryPath);
            EntryInternalUtils.Copy(sourceInfo, destInfo);
        }

        public void Delete(IDirectoryInfo item)
        {
            item.Delete();
        }

        public void Delete(string path)
        {
            IDirectoryInfo itemToDelete = (IDirectoryInfo)UserProfile.TryParseNonCachePath(path);
            if (itemToDelete == null) throw new System.IO.FileNotFoundException("Path not found", path);
            itemToDelete.Delete();
        }

        public bool Exists(string path)
        {
            bool isFolder;
            return COFEShared.PathParser.Exists(COFEShared.CurrentUserProfile, path, ParsableType.ParsePath, out isFolder) && isFolder;

            //IDirectoryInfo dir = UserProfile.TryParsePath(path) as IDirectoryInfo;
            //return dir != null;
        }

        public void Move(string sourceDirectoryPath, string destDirectoryPath)
        {
            IDirectoryInfo sourceInfo = (IDirectoryInfo)UserProfile.TryParseNonCachePath(sourceDirectoryPath);
            IDirectoryInfo destInfo = (IDirectoryInfo)UserProfile.TryParseNonCachePath(destDirectoryPath);
            if (sourceInfo == null) throw new System.IO.FileNotFoundException("Source not found", sourceDirectoryPath);
            if (destInfo == null) throw new System.IO.FileNotFoundException("Destation directory not found", destDirectoryPath);
            EntryInternalUtils.Move(sourceInfo, destInfo);
        }
        

        public string[] GetDirectories(string path, string searchPattern, SearchOptionEx searchOption)
        {
            IDirectoryInfo rootDir = (IDirectoryInfo)UserProfile.TryParsePath(path);
            if (rootDir == null) throw new System.IO.IOException(path + " is not a directory.");
            return rootDir.GetDirectories(searchPattern, searchOption).ToStringList();
        }

        public string[] GetDirectories(string path, string searchPattern)
        {
            return GetDirectories(path, searchPattern, SearchOptionEx.TopDirectoryOnly);
        }

        public string[] GetDirectories(string path)
        {
            return GetDirectories(path, "*", SearchOptionEx.TopDirectoryOnly);
        }

        public string[] GetFiles(string path, string searchPattern, SearchOptionEx searchOption)
        {
            IDirectoryInfo rootDir = (IDirectoryInfo)UserProfile.TryParsePath(path);
            if (rootDir == null) throw new System.IO.IOException(path + " is not a directory.");
            return rootDir.GetFiles(searchPattern, searchOption).ToStringList();
        }

        public string[] GetFiles(string path, string searchPattern)
        {
            return GetFiles(path, searchPattern, SearchOptionEx.TopDirectoryOnly);
        }

        public string[] GetFiles(string path)
        {
            return GetFiles(path, "*", SearchOptionEx.TopDirectoryOnly);
        }


        public string[] GetFileSystemEntries(string path, string searchPattern, SearchOptionEx searchOption)
        {
            IDirectoryInfo rootDir = (IDirectoryInfo)UserProfile.TryParsePath(path);
            if (rootDir == null) throw new System.IO.IOException(path + " is not a directory.");
            return rootDir.GetFileSystemInfos(searchPattern, searchOption).ToStringList();
        }

        public string[] GetFileSystemEntries(string path, string searchPattern)
        {
            return GetFileSystemEntries(path, searchPattern, SearchOptionEx.TopDirectoryOnly);
        }

        public string[] GetFileSystemEntries(string path)
        {
            return GetFileSystemEntries(path, "*", SearchOptionEx.TopDirectoryOnly);            
        }        

        public IDirectoryInfo GetParent(string path)
        {
            IDirectoryInfo rootDir = (IDirectoryInfo)UserProfile.TryParsePath(path);
            if (rootDir == null) throw new System.IO.IOException(path + " is not a directory.");
            return rootDir.Parent;
        }

        public string GetDirectoryRoot(string path)
        {
            IDirectoryInfo rootDir = (IDirectoryInfo)UserProfile.TryParsePath(path);
            if (rootDir == null) throw new System.IO.IOException(path + " is not a directory.");
            return rootDir.Root.FullName;
        }

        #endregion

        #region Data

        #endregion


        #region Public Properties

        public IUserProfile UserProfile { get; set; }

        #endregion




      
    }
}
